#include "circuit.h"
#include <string>
using namespace std;

bool Circuit::dumpHgates()
{
        int i,j,k;
        cout<<"Number of Hybrid gates is "<< hgateSize() << endl;
        for(i = 0; i < hgateSize(); i++)                                                                                                      
        {                                                                                                                                   
                cout << "HGate index "<< getHGate(i)->index <<endl;                                                                          
                
                cout << "dumping inputs! "<<endl;                                                                                                  
                for(j = 0; j < ((HybridNode*)getHGate(i))->getInputsSize(); j++)                                                                
                        cout<< ((HybridNode*)getHGate(i))->getInput(j) <<" : "<< getSignal( ((HybridNode*)getHGate(i))->getInput(j) )->getName() <<"\t";                                                          
                cout<<endl;                                                                                                                     
                
                cout << "dumping internal! "<<endl;                                                                                                  
                for(j = 0; j < ((HybridNode*)getHGate(i))->getInternalSize(); j++)                                                                
                        cout<< ((HybridNode*)getHGate(i))->getInternal(j) <<" : "<< getSignal( ((HybridNode*)getHGate(i))->getInternal(j) )->getName() <<"\t";                                                          
                cout<<endl;                                                                                                                     
                
                cout << "dumping outputs! "<<endl;                                                                                                  
                for(j = 0; j < ((HybridNode*)getHGate(i))->getOutputsSize(); j++)
                        cout<< ((HybridNode*)getHGate(i))->getOutput(j)<<" : "<< getSignal( ((HybridNode*)getHGate(i))->getOutput(j) )->getName() <<"\t";                                                  
                cout<<endl;                                                                                                                          
      
                cout << "dumping normal gates! "<<endl;                                                                                                  
                for(j = 0; j < ((HybridNode*)getHGate(i))->getIndexSize(); j++)                                                                  
                        cout<< ((HybridNode*)getHGate(i))->getIndex(j) <<"\t";                                                                          
                cout<<endl;                                                                                                                     
                
                //vector<int*>::iterator it;
                multimap<int,int* >::iterator it;
                pair<multimap<int,int* >::iterator,multimap<int,int* >::iterator> ret;
                
                cout << "dumping output forward restore '0'! "<<endl;                                                                                                  
                for(j = 0; j <((HybridNode*)getHGate(i))->getOutputsSize(); j++)
                {
                        cout<<"output "<<j<<endl;
                        ret = ((HybridNode*)getHGate(i))->FR0.equal_range(j);
                        for(it = ret.first; it != ret.second; it++)
                        {
                                for(k = 0; k < ((HybridNode*)getHGate(i))->getInputsSize() + ((HybridNode*)getHGate(i))->getOutputsSize()-1; k++)
                                        cout<<((*it).second)[k]<<"\t";
                                cout<<endl;
                        }
                }
                
                cout << "dumping output forward restore '1'! "<<endl;                                                                                                  
                for(j = 0; j <((HybridNode*)getHGate(i))->getOutputsSize(); j++)
                {
                        cout<<"output "<<j<<endl;
                        ret = ((HybridNode*)getHGate(i))->FR1.equal_range(j);
                        for(it = ret.first; it != ret.second; it++)
                        {
                                for(k = 0; k < ((HybridNode*)getHGate(i))->getInputsSize() + ((HybridNode*)getHGate(i))->getOutputsSize()-1; k++)
                                        cout<<((*it).second)[k]<<"\t";
                                cout<<endl;
                        }
                }
                                
                for(j = 0; j < 2 * ((HybridNode*)getHGate(i))->getInputsSize(); j++)
                {
                        cout<<"Back Track input "<< j/2 << " restore "<< j%2 <<endl;
                        for(k = 0; k < ((HybridNode*)getHGate(i))->getInputsSize(); k++)
                                cout<<((HybridNode*)getHGate(i))->events[j][k]<<"\t";
                        cout<<endl;
                }
                
                cout << "dumping extra backtrack "<<endl;                                                             
                for(it = ((HybridNode*)getHGate(i))->extra_events.begin(); it != ((HybridNode*)getHGate(i))->extra_events.end(); it++)
                {
                        cout<<"extra event for backtrack input "<< (*it)[0] << " for restore "<<(*it)[1] <<endl;
                        for(j = 0; j < ((HybridNode*)getHGate(i))->getInputsSize(); j++)
                                cout<< (*it)[j+2] <<"\t";
                        cout<<endl;
                }
                
                for(j = 0;  j < 2 * ((HybridNode*)getHGate(i))->getInputsSize(); j++)
                        cout<<"Backtrack input "<< j/2 <<" restore "<< j%2 << " event count is "<< ((HybridNode*)getHGate(i))->BR_event[j]<<endl;
                
                //for(j = 0;  j < ((HybridNode*)getHGate(i))->OFR0.size(); j++)
                //cout<<"Forward Restore 0 events count is " <<((HybridNode*)getHGate(i))->FR0_event[j]<<endl;
                
                //for(j = 0;  j < ((HybridNode*)getHGate(i))->OFR1.size(); j++)
                //cout<<"Forward Restore 1 events count is " <<((HybridNode*)getHGate(i))->FR1_event[j]<<endl;
                
                for(j = 0;  j < ((HybridNode*)getHGate(i))->extra_events.size(); j++)
                        cout<<"Backward Restore extra events count is "<< ((HybridNode*)getHGate(i))->Extra_br_event[j]<<endl;
        }                                                                                                                             
        
        return true;       
}


Circuit::~Circuit(){
	for(unsigned i=0; i<inputs.size();++i)
		delete inputs[i];
	for(unsigned i=0; i<outputs.size();++i)
		delete outputs[i];
	for(unsigned i=0; i<gates.size();++i)
		delete gates[i];
	for(unsigned i=0; i<flipflops.size();++i)
		delete flipflops[i];
		
	for(unsigned i=0; i<signals.size();++i)
		delete signals[i];
	return;
}

void Circuit::read_prob(char *filename){
	const int MAX_LINE_LENGTH       = 65536;
        char line_buffer[MAX_LINE_LENGTH];
        
        char s_tmp[10];
        float x_tmp;
        float y_tmp;
        
        ifstream inp(filename);
        if (!inp.is_open()) {
                cerr << "Can't open input file:" <<filename<< endl;
                exit(1);
        }
        while(!inp.eof()){
                inp.getline(line_buffer, MAX_LINE_LENGTH);
                sscanf (line_buffer, "%s = %f %f", s_tmp, &x_tmp, &y_tmp);
		
                Signal *s=addSignal(s_tmp);
                
                s->setP0(x_tmp);
                s->setP1(y_tmp);	
        }
	
}

void Circuit::write_prob(char *filename){
	ofstream outp(filename);
	for(int i=0; i<signalSize(); ++i)
		outp<<getSignal(i)->getName()<<" = "<<getSignal(i)->getP0()<<" "<<getSignal(i)->getP1()<<endl;
	outp.close();
}

Signal* Circuit::addSignal(string const s){
	for(unsigned i=0; i<signals.size(); ++i)
		if((s == signals[i]->getName()))
			return signals[i];
	Signal *tmp = new Signal(s);
	signals.push_back(tmp);
	return tmp;
}


